//
//  FGTextMessageCellData.m
//  FGChatKit
//
//  Created by Henry on 2020/8/13.
//  Copyright © 2020 Henry. All rights reserved.
//

#import "FGTextMessageCellData.h"
#import "FGKeyboardResources.h"
#import "FGKeyboardFaceGroup.h"
#import "FGKeyboardFaceItem.h"
#import "UIColor+FGChat.h"

#ifndef CGFLOAT_CEIL
#ifdef CGFLOAT_IS_DOUBLE
#define CGFLOAT_CEIL(value) ceil(value)
#else
#define CGFLOAT_CEIL(value) ceilf(value)
#endif
#endif

@interface FGTextMessageCellData ()

@property CGSize textSize;
@property CGPoint textOrigin;

@end

@implementation FGTextMessageCellData

- (instancetype)initWithDirection:(FGMsgDirection)direction {
    self = [super initWithDirection:direction];
    if (self) {
        _textFont = [UIFont systemFontOfSize:17];
        if (direction == FGMsgDirectionIncoming) {
            _textColor = [UIColor fg_colorWithLightColor:[UIColor blackColor] darkColor:[UIColor whiteColor]];
        } else {
            _textColor = [UIColor fg_colorWithLightColor:[UIColor blackColor] darkColor:[UIColor blackColor]];
        }
    }
    return self;
}

- (CGSize)contentSize {
    
    CGFloat textWidthMax = [UIScreen mainScreen].bounds.size.width * 0.6;
    
    CGRect rect = [self.attributedString boundingRectWithSize:CGSizeMake(textWidthMax, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];
    CGSize size = CGSizeMake(CGFLOAT_CEIL(rect.size.width), CGFLOAT_CEIL(rect.size.height));
    self.textSize = size;
    self.textOrigin = CGPointMake(self.cellLayout.bubbleInsets.left, self.cellLayout.bubbleInsets.top);

    size.height += self.cellLayout.bubbleInsets.top + self.cellLayout.bubbleInsets.bottom;
    size.width += self.cellLayout.bubbleInsets.left + self.cellLayout.bubbleInsets.right;

    if (self.direction == FGMsgDirectionIncoming) {
        size.height = MAX(size.height, [FGBubbleMessageCellData incommingBubble].size.height);
    } else {
        size.height = MAX(size.height, [FGBubbleMessageCellData outgoingBubble].size.height);
    }
    
    return size;
}

- (NSAttributedString *)attributedString {
    if (!_attributedString) {
        _attributedString = [self formatMessageString:_content];
    }
    return _attributedString;
}

- (NSArray *)getAttributeRange:(NSString *)text {
    // 先判断text是否存在
    if (text == nil || text.length == 0) {
        return @[];
    }
    
    NSMutableArray *arr = [NSMutableArray array];
    
    // 根据检测的类型初始化 这里是检测电话号码和网址
    NSError *error = nil;
    NSRange inputRange = NSMakeRange(0, text.length);
    
    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber | NSTextCheckingTypeLink error:&error];
    // 获得检测所得到的数组
    NSArray *matches = [detector matchesInString:text options:0 range:inputRange];
    
    for (NSTextCheckingResult *match in matches) {
        if ([match resultType] == NSTextCheckingTypeLink) {
            NSRange matchRange = [match range];
            [arr addObject:NSStringFromRange(matchRange)];
        }
        
        //当match匹配为电话号码时设置其attribute
        if ([match resultType] == NSTextCheckingTypePhoneNumber) {
            NSRange matchRange = [match range];
            [arr addObject:NSStringFromRange(matchRange)];
        }
    }
    
    return arr;
}

/// html转富文本
- (NSMutableAttributedString *)attForHtmlText:(NSString *)htmlText
{
    NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                              NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)};
    NSData *data = [htmlText dataUsingEncoding:NSUnicodeStringEncoding];
    NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithData:data
                                                                             options:options
                                                                  documentAttributes:nil
                                                                               error:nil];
    return att;
}

// TODO Face
- (NSAttributedString *)formatMessageString:(NSString *)text {
    
    // 先判断text是否存在
    if (text == nil || text.length == 0) {
        return [[NSMutableAttributedString alloc] initWithString:@""];
    }
    
    // 判断是不是html
    BOOL isHtml = [text hasPrefix:@"<"] && ([text hasSuffix:@">"] || [text hasSuffix:@"> "]);
    if (isHtml) {
        // 添加html头
        NSString *headerString = [NSString stringWithFormat:@"<header><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'><style>img{max-width:%d}</style></header>", (int)self.textFont.pointSize];
        text = [headerString stringByAppendingString:text];
        
        // html转NSMutableAttributedString
        NSMutableAttributedString *attributeString = [self attForHtmlText:text];
        
        // 处理"\n"开始
        if ([attributeString.string hasPrefix:@"\n"]) {
            [attributeString deleteCharactersInRange:NSMakeRange(0, 1)];
        }
        // 处理"\n"结束
        if ([attributeString.string hasSuffix:@"\n"]) {
            [attributeString deleteCharactersInRange:NSMakeRange(attributeString.string.length - 1, 1)];
        }
        // 处理"\U00002028"结束（就是<br>标签结束）
        if ([attributeString.string hasSuffix:@"\U00002028"]) {
            [attributeString deleteCharactersInRange:NSMakeRange(attributeString.string.length - 1, 1)];
        }
        
        // 判断html中是否有文字大小，设置文字大小
        if (![text containsString:@"font-size:"] && ![text containsString:@"</font>"]) {
            [attributeString addAttribute:NSFontAttributeName value:self.textFont range:NSMakeRange(0, attributeString.length)];
        }
        // 判断html中是否有文字颜色，设置文字颜色
        if (![text containsString:@"color="]) {
            [attributeString addAttribute:NSForegroundColorAttributeName value:self.textColor range:NSMakeRange(0, attributeString.length)];
        }
        return attributeString;
    }

    // 1、创建一个可变的属性字符串
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
    
    if ([FGKeyboardResources defaultFaceData].count == 0) {
        [attributeString addAttribute:NSFontAttributeName value:self.textFont range:NSMakeRange(0, attributeString.length)];
        return attributeString;
    }
    
    // 2、通过正则表达式来匹配字符串
    NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; //匹配表情
    NSError *error = nil;
    NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error];
    if (!re) {
        NSLog(@"%@", [error localizedDescription]);
        return attributeString;
    }
    
    NSArray *resultArray = [re matchesInString:text options:0 range:NSMakeRange(0, text.length)];

    FGKeyboardFaceGroup *group = [FGKeyboardResources defaultFaceData][0];

    // 3、获取所有的表情以及位置
    // 用来存放字典，字典中存储的是图片和图片对应的位置
    NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];
    // 根据匹配范围来用图片进行相应的替换
    for (NSTextCheckingResult *match in resultArray) {
        // 获取数组元素中得到range
        NSRange range = [match range];
        // 获取原字符串中对应的值
        NSString *subStr = [text substringWithRange:range];
        for (FGKeyboardFaceItem *face in group.faces) {
            if ([face.name isEqualToString:subStr]) {
                // face[i][@"png"]就是我们要加载的图片
                // 新建文字附件来存放我们的图片,iOS7才新加的对象
                NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
                // 给附件添加图片
                textAttachment.image = [UIImage imageWithContentsOfFile:face.path];
                // 调整一下图片的位置,如果你的图片偏上或者偏下，调整一下bounds的y值即可
                textAttachment.bounds = CGRectMake(0, -(self.textFont.lineHeight-self.textFont.pointSize)/2, self.textFont.pointSize, self.textFont.pointSize);
                // 把附件转换成可变字符串，用于替换掉源字符串中的表情文字
                NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
                // 把图片和图片对应的位置存入字典中
                NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];
                [imageDic setObject:imageStr forKey:@"image"];
                [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];
                // 把字典存入数组中
                [imageArray addObject:imageDic];
                break;
            }
        }
    }
    
    // 4、从后往前替换，否则会引起位置问题
    for (int i = (int)imageArray.count -1; i >= 0; i--) {
        NSRange range;
        [imageArray[i][@"range"] getValue:&range];
        // 进行替换
        [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];
    }

    [attributeString addAttribute:NSFontAttributeName value:self.textFont range:NSMakeRange(0, attributeString.length)];

    return attributeString;

//    // 根据检测的类型初始化 这里是检测电话号码和网址
//    NSError *error = nil;
//    NSRange inputRange = NSMakeRange(0, text.length);
//
//    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber | NSTextCheckingTypeLink error:&error];
//    // 获得检测所得到的数组
//    NSArray *matches = [detector matchesInString:text options:0 range:inputRange];
//
//    for (NSTextCheckingResult *match in matches) {
//        if ([match resultType] == NSTextCheckingTypeLink) {
//            NSRange matchRange = [match range]; // 这里可以自行设置
//            [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:matchRange];
//            // 下划线
//            [attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:matchRange];
//        }
//
//        //当match匹配为电话号码时设置其attribute
//        if ([match resultType] == NSTextCheckingTypePhoneNumber) {
//            NSRange matchRange = [match range]; //这里可以自行设置
//            [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:matchRange];
//            [attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:matchRange];
//        }
//    }
}

+ (NSString *)reuseIdentifier {
    return @"FGTextMessageCell";
}

@end
